tuple_size и наследуемый класс из кортежа?

#c #templates #compiler-errors #tuples #c 11

#c #шаблоны #ошибки компилятора #кортежи #c 11

Вопрос:

У меня есть следующий код:

 class TR_AgentInfo : public tuple<
                              long long,         //AgentId
                              string,         //AgentIp
                              >
{
public:
TR_AgentInfo() {}
TR_AgentInfo(
  const long longamp; AgentId,
  const stringamp; AgentIp,
   )
{
    get<0>(*this) = AgentId;
    get<1>(*this) = AgentIp;
}

long long getAgentId() const { return get<0>(*this); }
void setAgentId(const long longamp; AgentId) { get<0>(*this) = AgentId; }

string getAgentIp() const { return get<1>(*this); }
void setAgentIp(const stringamp; AgentIp) { get<1>(*this) = AgentIp; }
};
 

Теперь я хочу использовать этот код:

 int count = tuple_size<TR_AgentInfo>::value;
 

но gcc выдает эту ошибку:

 error: incomplete type std::tuple_size<TR_AgentInfo> used in nested name specifier
 

теперь , что я могу сделать ?

Комментарии:

1. В чем собственно проблема? Похоже, что размер кортежа всегда равен 2, так к чему эта гимнастика?

2. Я слишком упростил свой код! эти коды будут сгенерированы созданным мной TemplateGenerator, а затем будут использоваться в другой библиотеке шаблонов, которая является очень общей.

3. Почему вы не сохраняете размер кортежа как константу статического класса? Или введите кортеж, чтобы вы могли использовать его позже std::tuple_size<MyClass::tuple_type>::value ?

4. Я хочу, чтобы дочерний класс вел себя точно так же, как кортеж.

5. Если ваш класс завершен, тогда скажите namespace std { template<> struct tuple_size<TR_AgentInfo> { static const size_t value = 2; }; } . Добавление специализаций в пространство имен явно разрешено.

Ответ №1:

Если вы хотите, чтобы ваш единственный класс работал с std::tuple_size , вы можете просто указать специализацию:

 namespace std
{
  template<> struct tuple_size<TR_AgentInfo>
  {
    static const size_t value = 2;

    // alternatively, `tuple_size<tuple<long long, string>>::value`
    // or even better, `tuple_size<TR_AgentInfo::tuple_type>::value`, #1
  };
}
 

Вам явно разрешено добавлять специализации в пространство std имен, именно для ситуаций, подобных вашей.

Если ваш фактический класс сам по себе шаблонный, вы можете просто заменить 2 его соответствующей конструкцией. Например, для предложения № 1 вы могли бы добавить typedef для tuple_type своего класса. Есть много способов скинуть этот cat.

Ответ №2:

Если у вас есть экземпляр TR_AgentInfo kicking around, вы можете использовать вычет типа шаблона функции, чтобы сделать его более удобным, например:

 template <typename... T>
std::size_t get_tuple_size(std::tuple<T...> const amp;)
{
  return sizeof...(T);
}
 

и позвонить

 TR_AgentInfo info;
int count = get_tuple_size(info);
 

в противном случае вам нужно использовать правильное метапрограммирование, чтобы добраться до базового класса, но средства доступны.

Комментарии:

1. Я не хочу получать его в базовом классе. Мне нужно использовать tuple_size

2. Вы запрашиваете tuple_size класса, который не является кортежем. Базовый класс — это кортеж. Вы можете получить tuple_size этого базового класса. Или я что-то упускаю?

3. Я хочу получить tuple_size дочернего класса.

4.Как вы думаете, в чем разница? В каком смысле дочерний класс здесь отличается от кортежа базового класса? В конце концов, вы используете общедоступное наследование, чтобы явно выразить отношение IS-A, т. Е. Сказать, Что TR_AgentInfo это a tuple<long long, string> .